package com.xinsoft.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.ScmOutsourcingContractDTO;
import com.xinsoft.entity.dto.ScmOutsourcingContractLineClose;
import com.xinsoft.entity.dto.ScmOutsourcingContractParam;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.ScmOutsourcingContractDetailVo;
import com.xinsoft.entity.vo.ScmOutsourcingContractPageVo;
import com.xinsoft.mapper.ScmOutsourcingContractItemMapper;
import com.xinsoft.service.*;
import com.xinsoft.mapper.ScmOutsourcingContractMapper;
import com.xinsoft.utils.TokenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ZYM
 * @description 针对表【scm_outsourcing_contract(委外合同)】的数据库操作Service实现
 * @createDate 2023-08-29 16:23:20
 */
@Service
public class ScmOutsourcingContractServiceImpl extends ServiceImpl<ScmOutsourcingContractMapper, ScmOutsourcingContract>
        implements ScmOutsourcingContractService {


    @Resource
    private ScmOutsourcingContractItemMapper outsourcingContractItemMapper;
    @Autowired
    private ScmOutsourcingContractItemService outsourcingContractItemService;
    @Autowired
    private ScmOutsourcingContractPayService outsourcingContractPayService;
    @Autowired
    private ScmDocumentService scmDocumentService;
    @Autowired
    private SysDocumentNumService sysDocumentNumService;
    @Autowired
    private SysUserService sysUserService;

    @Override
    public IPage<ScmOutsourcingContractPageVo> findPageListByParam(ScmOutsourcingContractParam param) {
        if (param.getTabType() != null && param.getTabType() == 3) {
            Integer deptId = Objects.requireNonNull(TokenUtil.getUser()).getDeptId();
            List<SysUser> userList = sysUserService.list(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, deptId));
            List<Integer> userIdList = userList.stream().map(SysUser::getId).collect(Collectors.toList());
            param.setMyTeam(userIdList);
        }
        Page<ScmOutsourcingContractPageVo> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        IPage<ScmOutsourcingContractPageVo> pageList = baseMapper.findPageListByParam(page, param);
        return pageList;
    }

    @Override
    public List<ScmOutsourcingContractPageVo> findListByParam(ScmOutsourcingContractParam param) {
        return baseMapper.findPageListByParam(param);
    }

    @Override
    public Integer tempSave(ScmOutsourcingContractDTO dto) {
        ScmOutsourcingContract contract = new ScmOutsourcingContract();
        BeanUtils.copyProperties(dto, contract);
        contract.setAuditSign(Const.AUDIT_STATUS_WAIT);
        contract.setDoClose(Const.CloseStatus.NOT_CLOSED);
        contract.setApproveStatus(Const.ApproveStatus.STAGING);
        contract.setApplyPersonId(TokenUtil.getUserId());
        contract.setApplyTime(new Date());

        List<ScmOutsourcingContractItem> itemList = dto.getScmOutsourcingContractItemList();
        List<ScmOutsourcingContractPay> payList = dto.getScmOutsourcingContractPayList();
        if (Objects.isNull(contract.getId())) {
            int count = this.count(Wrappers.lambdaQuery(ScmOutsourcingContract.class)
                    .eq(ScmOutsourcingContract::getContractCode, contract.getContractCode()));
            if (count > 0) {
                throw new BDException("合同编号已存在，请重新生成");
            }
            // 更新流水号
            sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.OUTSOURCING_CONTRACT_DOCUMENT);
            // 保存委外合同主表
            this.save(contract);
        } else {
            // 删除物料列表
            List<ScmOutsourcingContractItem> items = outsourcingContractItemService.list(Wrappers.lambdaQuery(ScmOutsourcingContractItem.class)
                    .eq(ScmOutsourcingContractItem::getContractId, contract.getId()));
            List<Integer> itemIds = items.stream().map(ScmOutsourcingContractItem::getId).collect(Collectors.toList());
            outsourcingContractItemService.removeByIds(itemIds);

            // 删除附件与委外合同的关联关系
            scmDocumentService.remove(Wrappers.<ScmDocument>lambdaQuery().eq(ScmDocument::getScmId, contract.getId()));
            // 删除外合同付款条件
            outsourcingContractPayService.remove(Wrappers.lambdaQuery(ScmOutsourcingContractPay.class)
                    .eq(ScmOutsourcingContractPay::getContractId, contract.getId()));
            // 更新委外合同主表
            this.updateById(contract);
        }
        // 保存外合同明细
        itemList.forEach(item -> {
            item.setContractId(contract.getId());
            item.setDoClose(Const.CloseStatus.NOT_CLOSED);
        });
        outsourcingContractItemService.saveBatch(itemList);
        // 保存外合同付款条件
        payList.forEach(pay -> pay.setContractId(contract.getId()));
        outsourcingContractPayService.saveBatch(payList);
        // 保存附件关系
        List<SysFileHis> fileHisList = dto.getSysFileHisList();
        scmDocumentService.saveDocument(fileHisList, contract.getId(), Const.ApproveType.WWHT);
        return contract.getId();
    }

    @Override
    public ScmOutsourcingContractDetailVo detail(Integer id) {
        ScmOutsourcingContractDetailVo vo = baseMapper.getOutsourcingContractById(id);
        vo.setScmOutsourcingContractItemList(outsourcingContractItemMapper.listByContractId(id));
        List<ScmOutsourcingContractPay> payList = outsourcingContractPayService.list(Wrappers.lambdaQuery(ScmOutsourcingContractPay.class).eq(ScmOutsourcingContractPay::getContractId, id));
        vo.setScmOutsourcingContractPayList(payList);
        // 附件列表
        vo.setSysFileHisList(scmDocumentService.getFileHisListByScmId(id, Const.ApproveType.WWHT));
        return vo;
    }

    @Override
    public void del(List<Integer> ids) {
        List<ScmOutsourcingContract> saleList = this.list(Wrappers.lambdaQuery(ScmOutsourcingContract.class)
                .ne(ScmOutsourcingContract::getApproveStatus, Const.ApproveStatus.STAGING)
                .in(ScmOutsourcingContract::getId, ids));
        if (saleList.size() > 0) {
            throw new BDException("操作失败，只能删除暂存的委外合同");
        }
        scmDocumentService.remove(Wrappers.lambdaQuery(ScmDocument.class).in(ScmDocument::getScmId, ids).eq(ScmDocument::getScmType, Const.ApproveType.WWHT));
        outsourcingContractPayService.remove(Wrappers.lambdaQuery(ScmOutsourcingContractPay.class).in(ScmOutsourcingContractPay::getContractId, ids));
        outsourcingContractItemService.remove(Wrappers.lambdaQuery(ScmOutsourcingContractItem.class).in(ScmOutsourcingContractItem::getContractId, ids));
        this.removeByIds(ids);
    }

    @Override
    public void close(List<Integer> ids) {
        List<ScmOutsourcingContract> contractList = this.listByIds(ids);
        contractList.forEach(contract -> {
            if (Objects.equals(contract.getDoClose(), Const.CloseStatus.CLOSED)) {
                throw new BDException("委外合同已关闭，无需操作");
            }
            if (!Objects.equals(contract.getApproveStatus(), Const.ApproveStatus.APPROVED)) {
                throw new BDException("不能关闭未审批通过的委外合同");
            }
            contract.setDoClose(Const.CloseStatus.CLOSED);
        });
        this.updateBatchById(contractList);
    }

    @Override
    public void reverseClose(List<Integer> ids) {
        List<ScmOutsourcingContract> contractList = this.listByIds(ids);
        contractList.forEach(contract -> {
            if (Objects.equals(contract.getApproveStatus(), Const.CloseStatus.NOT_CLOSED)) {
                throw new BDException("委外合同未关闭，无需操作");
            }
            contract.setDoClose(Const.CloseStatus.NOT_CLOSED);
        });
        this.updateBatchById(contractList);
    }

    @Override
    public void lineClose(ScmOutsourcingContractLineClose dto) {
        List<ScmOutsourcingContractItem> items = new ArrayList<>();
        dto.getIds().forEach(id -> {
            ScmOutsourcingContractItem item = new ScmOutsourcingContractItem();
            item.setId(id);
            item.setCloseTime(new Date());
            item.setDoClose(Const.CloseStatus.CLOSED);
            item.setCloseReason(dto.getCloseReason());
            items.add(item);
        });
        outsourcingContractItemService.updateBatchById(items);
    }
}




